#include "StdAfx.h"
#include "ClassCalc.h"
#include "logproc.h"
#include "GameMain.h"
#include "LuaFun.h"
#include "LuaExport.h"
#include "MasterLevelSkillTreeSystem.h"

ClassCalc g_ClassCalc;

void ClassCalc::SetClass(LPOBJ lpUser, MULua * Lua)
{
	lua_State * pLuaState = Lua->GetLua();

	if (pLuaState == NULL)
	{
		LogAddC(2, "[ClassCalc] Error [%s] [%d]", __FILE__, __LINE__);
		return;
	}

	this->m_Bind[0].Name	= "Level";
	this->m_Bind[0].Varible	= lpUser->Level;
	this->m_Bind[1].Name	= "MasterLevel";
	this->m_Bind[1].Varible	= lpUser->m_nMasterLevel;
	this->m_Bind[2].Name	= "Reset";
	this->m_Bind[2].Varible	= lpUser->Reset;
	this->m_Bind[3].Name	= "AttackSpeed";
	this->m_Bind[3].Varible	= lpUser->m_AttackSpeed;
	this->m_Bind[4].Name	= "MagicSpeed";
	this->m_Bind[4].Varible	= lpUser->m_MagicSpeed;
	this->m_Bind[5].Name	= "Strength";
	this->m_Bind[5].Varible	= lpUser->Strength;
	this->m_Bind[6].Name	= "Dexterity";
	this->m_Bind[6].Varible	= lpUser->Dexterity;
	this->m_Bind[7].Name	= "Vitality";
	this->m_Bind[7].Varible	= lpUser->Vitality;
	this->m_Bind[8].Name	= "Energy";
	this->m_Bind[8].Varible	= lpUser->Energy;
	this->m_Bind[9].Name	= "Command";
	this->m_Bind[9].Varible	= lpUser->Leadership;
	this->m_Bind[10].Name	= "Class";
	this->m_Bind[10].Varible = lpUser->Class;
	const struct luaL_Reg ClassReg[] =
	{
		{ "__index",	this->GetClassVar	},
		{ NULL,			NULL				},
	};
	lua_newuserdata(pLuaState, sizeof(this->m_Bind));
	luaL_newmetatable(pLuaState, "ClassReg");
	luaL_register(pLuaState, "lpUser", ClassReg);
	lua_setmetatable(pLuaState, -2);
	lua_setglobal(pLuaState, "lpUser");

	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return;
	}

	Lua->DoFile(gDirPath.GetNewPath("Custom\\ClassCalc.lua"));
}

int ClassCalc::GetClassVar(lua_State * Lua)
{
	const char * Varible = luaL_checkstring(Lua, 2);

	for(int i = 0; i < (sizeof(g_ClassCalc.m_Bind) / sizeof(g_ClassCalc.m_Bind[0])); i++)
	{
		if (!strcmp(g_ClassCalc.m_Bind[i].Name, Varible))
		{
			lua_pushinteger(Lua, g_ClassCalc.m_Bind[i].Varible);
			return true;
		}
	}

	return false;
}

int ClassCalc::GetLevelPoint(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int LevelPoint = 0;
	g_Generic_Call(Lua->GetLua(), "GetLevelPoint", ">i", &LevelPoint);
	Lua->Release();
	delete Lua;
	return LevelPoint;
}

bool ClassCalc::GetAttackDamage(LPOBJ lpUser, bool bWithBow)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int AttackDamageMinRight	= 0;
	int AttackDamageMaxRight	= 0;
	int AttackDamageMinLeft		= 0;
	int AttackDamageMaxLeft		= 0;
	g_Generic_Call(Lua->GetLua(), "GetAttackDamage", "i>iiii", bWithBow,
		&AttackDamageMinRight, &AttackDamageMaxRight,
		&AttackDamageMinLeft, &AttackDamageMaxLeft);
	Lua->Release();
	lpUser->m_AttackDamageMinRight	= AttackDamageMinRight;
	lpUser->m_AttackDamageMaxRight	= AttackDamageMaxRight;
	lpUser->m_AttackDamageMinLeft	= AttackDamageMinLeft;
	lpUser->m_AttackDamageMaxLeft	= AttackDamageMaxLeft;
	delete Lua;
	return true;
}

bool ClassCalc::GetMagicDamage(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int MagicDamageMin	= 0;
	int MagicDamageMax	= 0;
	g_Generic_Call(Lua->GetLua(), "GetMagicDamage", ">ii",
		&MagicDamageMin, &MagicDamageMax);
	Lua->Release();
	lpUser->m_MagicDamageMin	= MagicDamageMin;
	lpUser->m_MagicDamageMax	= MagicDamageMax;
	delete Lua;
	return true;
}

float ClassCalc::GetPvPAttackRate(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	double fAttackRate = 0.0f;
	g_Generic_Call(Lua->GetLua(), "GetPvPAttackRate", ">d", &fAttackRate);
	Lua->Release();
	delete Lua;
	return (float)fAttackRate;
}

bool ClassCalc::GetAttackSpeed(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int AttackSpeed = 0;
	int MagicSpeed	= 0;
	g_Generic_Call(Lua->GetLua(), "GetAttackSpeed", ">ii", &AttackSpeed, &MagicSpeed);
	Lua->Release();
	lpUser->m_AttackSpeed	= AttackSpeed;
	lpUser->m_MagicSpeed	= MagicSpeed;
	delete Lua;
	return true;
}

bool ClassCalc::GetDefense(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int Defense = 0;
	g_Generic_Call(Lua->GetLua(), "GetDefense", ">i", &Defense);
	Lua->Release();
	lpUser->m_Defense = Defense;
	delete Lua;
	return true;
}

float ClassCalc::GetPvPDefenseRate(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	double fDefenseRate = 0.0f;
	g_Generic_Call(Lua->GetLua(), "GetPvPDefenseRate", ">d", &fDefenseRate);
	Lua->Release();
	delete Lua;
	return (float)fDefenseRate;
}

bool ClassCalc::GetSuccessfulBlocking(LPOBJ lpUser)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int SuccessfulBlocking = 0;
	g_Generic_Call(Lua->GetLua(), "GetSuccessfulBlocking", ">i", &SuccessfulBlocking);
	Lua->Release();
	lpUser->m_SuccessfulBlocking = SuccessfulBlocking;
	delete Lua;
	return true;
}

bool ClassCalc::GetDarkSpiritStats(LPOBJ lpUser, CDarkSpirit * Pet, int PetLevel)
{
	if (lpUser->Connected != PLAYER_PLAYING)
	{
		return false;
	}

	MULua * Lua = new MULua;
	this->SetClass(lpUser, Lua);
	int AttackDamageMin			= 0;
	int AttackDamageMax			= 0;
	double CriticalAttackRate	= 0.0f;
	int AttackSpeed				= 0;
	int SuccessAttackRate		= 0;
	g_Generic_Call(Lua->GetLua(), "GetDarkSpiritStats", "i>iidii", PetLevel,
		&AttackDamageMin, &AttackDamageMax, &CriticalAttackRate,
		&AttackSpeed, &SuccessAttackRate);
	Lua->Release();
	Pet->m_AttackDamageMin		= AttackDamageMin;
	Pet->m_AttackDamageMax		= AttackDamageMax;
	Pet->m_CriticalAttackRate	= (float)CriticalAttackRate;
	Pet->m_AttackSpeed			= AttackSpeed;
	Pet->m_SuccessAttackRate	= SuccessAttackRate;
	delete Lua;
	return true;
}